package br.unifor.cct.mia.evaluate;

import java.awt.Point;
import java.util.List;
import java.util.Map;

import br.unifor.cct.mia.dataenhancement.Database;
import br.unifor.cct.mia.dataenhancement.Structure;
import br.unifor.cct.mia.evolutionary.Genotype;
import br.unifor.cct.mia.ga.Ga;
import br.unifor.cct.mia.util.Methods;

public class RuleInterest implements Evaluate {
	
	private List positions;
	private Structure structure;
	private Database database, dbAux;
	private Map genesAnt;
	private String[] options;
	
	public double cost(Genotype gen) {		
		double sum = 0;
		double CandP = 0, C = 0, P = 0, S = database.size();
		
		Integer hashCode = new Integer(gen.hashCode());
		if (!genesAnt.containsKey(hashCode)) {			
			dbAux = (Database)database.clone();
			dbAux.updateValues(positions, structure.getStringValues(positions, gen.getGene()));
		
			int[] result;
			for (int i = 0; i < gen.getGene().length; i++) {
				result = dbAux.conditionAndPrediction((Point)positions.get(i));			
				CandP = result[0];
				C = result[1];
				P = result[2];			
				sum += CandP - (C * P) / S;
			}
			
			genesAnt.put(hashCode, new Double(sum));
		}
		else {
			sum = ((Double)genesAnt.get(hashCode)).doubleValue();
		}
		return sum;
	}

	public Object evaluate(Object value,String[] options) {
		this.options = options;              
		Object[] o = (Object[]) value;
		positions = (List)o[0];
		database = (Database)o[1];
		structure = (Structure)o[2];
		genesAnt = (Map) o[3];
		Ga Ga = (Ga)o[4];
		
		Ga.indexBestWorst[0] = Ga.indexBestWorst[1] = 0;
       
		//long total = 0;
        for(int i = 0; i < Ga.configurations.getPopsize(); i++) {
        	//long ini = System.currentTimeMillis()/1000;
        	
        	Ga.population[i].setFitness(cost((Genotype)Ga.population[i]));            

        	//long fim = System.currentTimeMillis()/1000;
        	//System.out.println("T2 - T1 = "+(fim-ini));
        	//total += (fim-ini);
        	
            if (Ga.population[i].getFitness() > Ga.population[Ga.indexBestWorst[0]].getFitness()) 
            	Ga.indexBestWorst[0] = i;
            else 
            	if (Ga.population[i].getFitness() < Ga.population[Ga.indexBestWorst[1]].getFitness()) 
            		Ga.indexBestWorst[1] = i;
        }
        
        //System.out.println("Total = "+total);
        
		return Ga.population;
	}
}
